package com.simpleplayer.views.videoview;

import android.annotation.SuppressLint;
import android.content.Context;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;

import com.simpleplayer.R;
import com.simpleplayer.MediaPlayer.SimplePlayer;
import com.simpleplayer.services.LogUtil;
import com.simpleplayer.services.TimeUtil;
import com.simpleplayer.views.customview.CustomTextView;

@SuppressLint("ViewConstructor")
class InlineVideoView extends VideoViewInternal {

    private static final String TAG = "InlineVideoView";

    private static final int HIDE_CONTROLS_DELAY = 5000; // 单位: 毫秒
    private static final int MAX_SEEK_BAR_PROGRESS = 1000;
    private static final int SEEK_BAR_INCREMENT = 1; // 进度条增量

    private ViewGroup mInlineContainer;
    private ViewGroup mControlsContainer;
    private ViewGroup mContentContainer;
    private ImageView mPlayButton;
    private ImageView mEnterFloatWindowButton;
    private ImageView mEnterFullscreenButton;
    private SeekBar mSeekBar;
    private CustomTextView mInfosView;
    private TextView mProgressInfoView;

    private final Context mContext;
    private final VideoView mParent;
    private final SimplePlayer mPlayer;
    private Runnable mHideControlsTask;
    private boolean mDragSeekBar = false; // 是否在拖动进度条
    private boolean mShowingControls = false; // 是否正在显示视频控件

    public InlineVideoView(Context context, SimplePlayer player, VideoView parent) {
        super(context);
        mContext = context;
        mParent = parent;
        mPlayer = player;

        initViews();
        initCommon();
    }

    @SuppressLint("ClickableViewAccessibility")
    private void initViews() {
        View.inflate(mContext, R.layout.inline_video_view, this);

        mInlineContainer = findViewById(R.id.inline_container);
        mControlsContainer = findViewById(R.id.inline_controls_container);
        mContentContainer = findViewById(R.id.inline_content_container);
        mPlayButton = findViewById(R.id.inline_play_button);
        mEnterFloatWindowButton = findViewById(R.id.inline_float_button);
        mEnterFullscreenButton = findViewById(R.id.inline_fullscreen_button);
        mInfosView = findViewById(R.id.player_info);
        mProgressInfoView = findViewById(R.id.inline_progress_info);
        mSeekBar = findViewById(R.id.inline_progress_bar);

        InlineViewsEventDispatcher eventDispatcher = new InlineViewsEventDispatcher();
        mPlayButton.setOnClickListener(eventDispatcher);
        mEnterFloatWindowButton.setOnClickListener(eventDispatcher);
        mEnterFullscreenButton.setOnClickListener(eventDispatcher);
        mInlineContainer.setOnClickListener(eventDispatcher);
        mInlineContainer.setOnTouchListener(eventDispatcher);
        mContentContainer.setOnClickListener(eventDispatcher);
        mSeekBar.setOnSeekBarChangeListener(new CustomSeekBarChangeListener());
        mSeekBar.setMax(MAX_SEEK_BAR_PROGRESS);
        mSeekBar.setKeyProgressIncrement(SEEK_BAR_INCREMENT);
    }

    private void initCommon() {
        setLayoutParams(
            new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT
            )
        );

        mPlayer.addListener(new SimplePlayerListener());
    }

    @Override
    public void setContentView(View contentView) {
        if (contentView == null) return;
        // 将view从其父容器移除
        ViewParent parent = contentView.getParent();
        if (parent instanceof ViewGroup) {
            ((ViewGroup)parent).removeView(contentView);
        }

        // 替换展示的view
        if (mContentContainer.getChildCount() != 0) {
            mContentContainer.removeAllViews();
        }
        mContentContainer.addView(contentView);
    }

    // ---------------------------------------------------------------------------------------------
    // 控件显示/隐藏
    private void showControlsOnce() {
        // 显示小屏控件，5s后自动消失
        mShowingControls = true;
        mControlsContainer.setVisibility(VISIBLE);
        hideControlsDelay(HIDE_CONTROLS_DELAY);
    }

    private void showControls() {
        mShowingControls = true;
        mControlsContainer.setVisibility(VISIBLE);
        if (mHideControlsTask != null) {
            getHandler().removeCallbacks(mHideControlsTask);
        }
    }

    private void hideControls() {
        mShowingControls = false;
        mControlsContainer.setVisibility(INVISIBLE);
    }

    private void hideControlsDelay(long delayMillis) {
        // 延迟delayMillis(ms)后隐藏控件
        if (mHideControlsTask == null) {
            mHideControlsTask = this::hideControls;
        }
        getHandler().removeCallbacks(mHideControlsTask);
        getHandler().postDelayed(mHideControlsTask, delayMillis);
    }
    // ---------------------------------------------------------------------------------------------

    @SuppressLint("SetTextI18n")
    private void updateTime() {
        long durationMs = mPlayer.getDuration();
        if (mDragSeekBar) {
            // 拖动进度条时，进度信息随进度条变化
            long timeMs = mSeekBar.getProgress() * durationMs / mSeekBar.getMax();
            mProgressInfoView.setText(
                TimeUtil.secToTime(timeMs / 1000) + "/" + TimeUtil.secToTime(durationMs / 1000)
            );
        } else {
            // 未拖动进度条时，进度信息随视频变化
            long timeMs = mPlayer.getCurrentPosition();
            mSeekBar.setProgress((int) (timeMs * mSeekBar.getMax() / durationMs));
            mProgressInfoView.setText(
                TimeUtil.secToTime(timeMs / 1000) + "/" + TimeUtil.secToTime(durationMs / 1000)
            );
        }
    }

    @SuppressLint("SetTextI18n")
    private void updateDuration() {
        long timeMs = mPlayer.getCurrentPosition();
        long durationMs = mPlayer.getDuration();
        mSeekBar.setMax(Math.max(MAX_SEEK_BAR_PROGRESS, (int)mPlayer.getDuration()));
        mProgressInfoView.setText(
            TimeUtil.secToTime(timeMs / 1000) + "/" + TimeUtil.secToTime(durationMs / 1000)
        );
    }

    // ---------------------------------------------------------------------------------------------
    // Listener 定义

    /**
     * inline 模式下的 view 事件处理
     * 单击：显示一次视频控件
     * 长按：永久显示视频控件，直至长按结束
     */
    private class InlineViewsEventDispatcher implements View.OnClickListener, View.OnTouchListener {
        @Override
        public void onClick(View v) {
            if (mEnterFloatWindowButton.equals(v)) {
                // 进入小窗
                mParent.switchDisplayModeTo(VideoView.FLOATWINDOW);
                return;
            } else if (mEnterFullscreenButton.equals(v)) {
                // 进入全屏
                mParent.switchDisplayModeTo(VideoView.FULLSCREEN);
                return;
            } else if (mPlayButton.equals(v)) {
                // 播放/暂停
                mPlayer.toggle();
            } else if (mContentContainer.equals(v)) {
                if (mShowingControls) {
                    mPlayer.toggle();
                }
            }
            showControlsOnce();
        }

        @SuppressLint("ClickableViewAccessibility")
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                // 开始按压，显示控件
                showControls();
            } else if (event.getAction() == MotionEvent.ACTION_UP) {
                // 按压结束，隐藏控件
                hideControlsDelay(HIDE_CONTROLS_DELAY);
            }
            return false;
        }
    }

    /**
     * 自定义进度条事件.
     * 拖动进度条更新视频位置
     */
    private class CustomSeekBarChangeListener implements SeekBar.OnSeekBarChangeListener {

        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            if (fromUser) {
                updateTime();
            }
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
            // 开始拖动进度条
            LogUtil.i(TAG, "Seekbar StartTrackingTouch");
            mDragSeekBar = true;
            showControls();
        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            LogUtil.i(TAG, "Seekbar StopTrackingTouch");
            mDragSeekBar = false;
            int progress = seekBar.getProgress();
            mPlayer.seekTo(progress * mPlayer.getDuration() / mSeekBar.getMax());
            hideControlsDelay(HIDE_CONTROLS_DELAY);
        }
    }

    /**
     * 播放器事件监听
     */
    private class SimplePlayerListener implements SimplePlayer.Listener {
        @Override
        public void onStateChanged(int oldState, int newState) {
            switch (newState) {
                case SimplePlayer.PREPARING:
                    mInfosView.setTextAndShow(R.string.video_preparing_info);
                    break;
                case SimplePlayer.PREPARED:
                    mInfosView.setTextAndShow(R.string.video_preparing_info);
                    updateDuration();
                    break;
                case SimplePlayer.PLAYING:
                    mInfosView.clearAndHide();
                    mPlayButton.setBackgroundResource(R.drawable.ic_pause);
                    setKeepScreenOn(true);
                    break;
                case SimplePlayer.PAUSE:
                    mPlayButton.setBackgroundResource(R.drawable.ic_play);
                    setKeepScreenOn(false);
                    break;
                case SimplePlayer.STOP:
                    mPlayer.removeListener(SimplePlayerListener.this);
                    break;
                case SimplePlayer.ERROR:
                    mInfosView.setTextAndShow(R.string.video_error_info);
                    break;
                default:
                    break;
            }
        }

        @Override
        public void onTimeChanged(long timeMs) {
            updateTime();
        }

        @Override
        public void onBufferingStart() {
            if (mPlayer.getCurrentDisPlayMode() != SimplePlayer.INLINE) return;
            mPlayer.stopCalculateBandwidth();
            mPlayer.startCalculateBandwidth(100, bandwidthEstimate -> {
                mInfosView.setTextAndShow("视频正在缓冲中: " + bandwidthEstimate + "kb/s");
            });
        }

        @Override
        public void onBufferingEnd() {
            if (mPlayer.getCurrentDisPlayMode() != SimplePlayer.INLINE) return;
            mPlayer.stopCalculateBandwidth();
            mInfosView.clearAndHide();
        }
    }
    // ---------------------------------------------------------------------------------------------
}
